#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "ConnectableElement.h"
#include "MultiplicityElement.h"
#include "NamedElement.h"
#include "ParameterDirectionKind.h"
#include "ParameterEffectKind.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Operation;
class ParameterSet;
class ValueSpecification;

/// <summary>
/// Parameter
/// A Parameter is a specification of an argument used to pass information into or
/// out of an invocation of a BehavioralFeature.  Parameters can be treated as
/// ConnectableElements within Collaborations.
/// </summary>
class UMLMODEL_EXPORT Parameter
    : public MultiplicityElement
    , public ConnectableElement
    , public NamedElement {

public: // Constructors and destructors
    explicit Parameter(const QString& umlType = "uml::Parameter");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
public: // Properties
    /// <summary>
    /// default2 getter
    /// A String that represents a value to be used when no argument is supplied for the
    /// Parameter.
    /// </summary>
    QString default2() const;

    /// <summary>
    /// default2 setter
    /// A String that represents a value to be used when no argument is supplied for the
    /// Parameter.
    /// </summary>
    void setDefault2(const QString& value);

    /// <summary>
    /// defaultValue getter
    /// Specifies a ValueSpecification that represents a value to be used when no
    /// argument is supplied for the Parameter.
    /// </summary>
    shared_ptr<ValueSpecification> defaultValue() const;

    /// <summary>
    /// defaultValue setter
    /// Specifies a ValueSpecification that represents a value to be used when no
    /// argument is supplied for the Parameter.
    /// </summary>
    void setDefaultValue(shared_ptr<ValueSpecification> value);

    /// <summary>
    /// direction getter
    /// Indicates whether a parameter is being sent into or out of a behavioral element.
    /// </summary>
    ParameterDirectionKind direction() const;

    /// <summary>
    /// direction setter
    /// Indicates whether a parameter is being sent into or out of a behavioral element.
    /// </summary>
    void setDirection(ParameterDirectionKind value);

    /// <summary>
    /// effect getter
    /// Specifies the effect that executions of the owner of the Parameter have on
    /// objects passed in or out of the parameter.
    /// </summary>
    ParameterEffectKind effect() const;

    /// <summary>
    /// effect setter
    /// Specifies the effect that executions of the owner of the Parameter have on
    /// objects passed in or out of the parameter.
    /// </summary>
    void setEffect(ParameterEffectKind value);

    /// <summary>
    /// isException getter
    /// Tells whether an output parameter may emit a value to the exclusion of the other
    /// outputs.
    /// </summary>
    bool isException() const;

    /// <summary>
    /// isException setter
    /// Tells whether an output parameter may emit a value to the exclusion of the other
    /// outputs.
    /// </summary>
    void setIsException(bool value);

    /// <summary>
    /// isStream getter
    /// Tells whether an input parameter may accept values while its behavior is
    /// executing, or whether an output parameter may post values while the behavior is
    /// executing.
    /// </summary>
    bool isStream() const;

    /// <summary>
    /// isStream setter
    /// Tells whether an input parameter may accept values while its behavior is
    /// executing, or whether an output parameter may post values while the behavior is
    /// executing.
    /// </summary>
    void setIsStream(bool value);

    /// <summary>
    /// operation getter
    /// The Operation owning this parameter.
    /// </summary>
    shared_ptr<Operation> operation() const;

    /// <summary>
    /// operation setter
    /// The Operation owning this parameter.
    /// </summary>
    void setOperation(shared_ptr<Operation> value);

    /// <summary>
    /// parameterSets getter
    /// The ParameterSets containing the parameter. See ParameterSet.
    /// </summary>
    vector<shared_ptr<ParameterSet>>& parameterSets();

private: // Fields
    /// <summary>
    /// default2
    /// A String that represents a value to be used when no argument is supplied for the
    /// Parameter.
    /// </summary>
    const static QString default2_default_;
    QString default2_ = default2_default_;

    /// <summary>
    /// defaultValue
    /// Specifies a ValueSpecification that represents a value to be used when no
    /// argument is supplied for the Parameter.
    /// </summary>
    shared_ptr<ValueSpecification> defaultValue_;

    /// <summary>
    /// direction
    /// Indicates whether a parameter is being sent into or out of a behavioral element.
    /// </summary>
    ParameterDirectionKind direction_ = ParameterDirectionKind::kin;

    /// <summary>
    /// effect
    /// Specifies the effect that executions of the owner of the Parameter have on
    /// objects passed in or out of the parameter.
    /// </summary>
    ParameterEffectKind effect_ = ParameterEffectKind::kcreate;

    /// <summary>
    /// isException
    /// Tells whether an output parameter may emit a value to the exclusion of the other
    /// outputs.
    /// </summary>
    const static bool isException_default_;
    bool isException_ = isException_default_;

    /// <summary>
    /// isStream
    /// Tells whether an input parameter may accept values while its behavior is
    /// executing, or whether an output parameter may post values while the behavior is
    /// executing.
    /// </summary>
    const static bool isStream_default_;
    bool isStream_ = isStream_default_;

    /// <summary>
    /// operation
    /// The Operation owning this parameter.
    /// </summary>
    shared_ptr<Operation> operation_;

    /// <summary>
    /// parameterSets
    /// The ParameterSets containing the parameter. See ParameterSet.
    /// </summary>
    vector<shared_ptr<ParameterSet>> parameterSets_;
};

} // namespace uml
